﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace The_LarX
{
    public class Renderer_Advanced : Renderer
    {
        /*public Effect PostProcEffect;

        private List<ILight> Lights;
        private List<Actor> Actors;

        private AdvancedEffect AdvancedEffect;

        public Renderer_Advanced()
        {
            Effect = new AdvancedEffect(Engine.Content.Load<Effect>("Engine\\Effects\\fx_Advanced"));
            AdvancedEffect = (AdvancedEffect)Effect;

            Lights = new List<ILight>();
            Actors = new List<Actor>();
        }

        private List<Model> models = new List<Model>();
        public override void RemapModel(ref Model Model)
        {
            if (!models.Contains(Model))
            {
                models.Add(Model);
                foreach (ModelMesh mesh in Model.Meshes)
                {
                    foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    {
                        Effect newEffect = Effect.Clone();
                        meshPart.Effect = newEffect;
                    }
                }
            }
        }

        public override void SubmitActor(Actor actor)
        {
            Actors.Add(actor);
        }

        public override void SubmitLight(object Light)
        {
            if (Light is ILight)
                Lights.Add((ILight)Light);
        }

        /// <summary>
        /// Render all the Stored Actors, with the Stored Lights. This method
        /// WILL clear the BackBuffer
        /// </summary>
        public override void RenderActors()
        {
            if (Camera != null)
            {
                for (int i = 0; i < Actors.Count; i++)
                {
                    DrawActor(Actors[i]);
                }
            }
            Actors.Clear();
            Lights.Clear();
        }

        private void DrawActor(Actor Obj)
        {
            if (Obj.Model == null)
                return;

            GraphicsDevice device = Engine.GraphicsDevice;

            device.BlendState = BlendState.Opaque;
            device.DepthStencilState = DepthStencilState.Default;
            device.RasterizerState = RasterizerState.CullCounterClockwise;
            device.SamplerStates[0] = SamplerState.LinearWrap;

            Matrix[] AbsolutTransforms = new Matrix[Obj.Model.Bones.Count];
            Obj.Model.CopyAbsoluteBoneTransformsTo(AbsolutTransforms);

            CullMode lastCull = device.RasterizerState.CullMode;

            // Draw the model.
            foreach (ModelMesh mesh in Obj.Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {                    
                    if (part.VertexBuffer.IsDisposed)
                    {
                        return;
                    }
                }
                foreach (Effect effect in mesh.Effects)
                {
                    if (effect is BasicEffect)
                    {
                        return;
                    }
                    // Specify which effect technique to use.
                    effect.CurrentTechnique = effect.Techniques["PerPixel"];

                    Matrix localWorld = AbsolutTransforms[mesh.ParentBone.Index] * Obj.World;

                    // Camera Parameters
                    effect.Parameters["View"].SetValue(Camera.View);
                    effect.Parameters["Projection"].SetValue(Camera.Projection);
                    // Object Parameters
                    effect.Parameters["World"].SetValue(localWorld);
                    // Light Parameters           
                    int LightsCount = Lights.Count;
                    Vector3[] Positions = new Vector3[LightsCount];
                    Vector4[] Colors = new Vector4[LightsCount];
                    float[] Powers = new float[LightsCount];
                    for (int i = 0; i < LightsCount; i++)
                    {
                        Positions.SetValue(Lights[i].Position, i);
                        Colors.SetValue(Lights[i].Color, i);
                        Powers.SetValue(Lights[i].Power, i);
                    }
                    effect.Parameters["LightsPositions"].SetValue(Positions);
                    effect.Parameters["LightsColors"].SetValue(Colors);
                    effect.Parameters["LightsPowers"].SetValue(Powers);
                    /*
                    // Material Parameters
                    effect.Parameters["Texture"].SetValue(Obj.Material.Texture);
                    effect.Parameters["Textured"].SetValue(Obj.Material.Textured);
                    effect.Parameters["DiffuseColor"].SetValue(Obj.Material.DiffuseColor);
                    effect.Parameters["SelfIllumination"].SetValue(Obj.Material.SelfIllumination);
                    effect.Parameters["Tile"].SetValue(Obj.Material.Tile);

                    //effect.Parameters["Bumped"].SetValue(Obj.Material.Bumped);
                    //effect.Parameters["xBumpMap"].SetValue(Obj.Material.BumpTex);
                    //effect.Parameters["BumpConstant"].SetValue(Obj.Material.BumpConstant);
                    // Camera Parameters
                    effect.Parameters["View"].SetValue(Camera.View);
                    effect.Parameters["Projection"].SetValue(Camera.Projection);
                    // Light Parameters           
                    List<Vector3> Positions = new List<Vector3>();
                    List<Vector4> Colors = new List<Vector4>();
                    List<float> Powers = new List<float>();
                    for (int i = 0; i < Lights.Count; i++)
                    {
                        Positions.Add(Lights[i].Position);
                        Colors.Add(Lights[i].Color);
                        Powers.Add(Lights[i].Power);
                    }
                    effect.Parameters["LightsPositions"].SetValue(Positions.ToArray());
                    effect.Parameters["LightsColors"].SetValue(Colors.ToArray());
                    effect.Parameters["LightsPowers"].SetValue(Powers.ToArray());
                    // Light Ambient
                    effect.Parameters["LightAmbient"].SetValue(Engine.Render.LightAmbient);
                    effect.Parameters["LightNumber"].SetValue(Lights.Count);
                    effect.Parameters["LightsMaxDistance"].SetValue(Engine.Render.LightMaxDistance);
                    */                
                /*mesh.Draw();
            }
        }*/
    //}
    }
}
